package com.unidt.www.module.bpm.framework.flowable.core.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.ImmutableSet;
import com.unidt.www.module.bpm.dal.dataobject.task.BpmDynamicAssignDo;
import com.unidt.www.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import com.unidt.www.module.bpm.dal.mysql.task.BpmDynamicAssignMapper;
import com.unidt.www.module.bpm.framework.bpm.core.processor.TaskDeadTimeProcessor;
import com.unidt.www.module.bpm.service.task.BpmActivityService;
import com.unidt.www.module.bpm.service.task.BpmTaskNotifyService;
import com.unidt.www.module.bpm.service.task.BpmTaskService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 监听 {@link org.flowable.task.api.Task} 的开始与完成，创建与更新对应的 {@link BpmTaskExtDO} 记录
 *
 * @author jason
 */
@Component
@Slf4j
public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {

    @Resource
    @Lazy // 解决循环依赖
    private BpmTaskService taskService;


    @Resource
    @Lazy // 解决循环依赖
    private BpmActivityService activityService;

    @Resource
    @Lazy // 解决循环依赖
    BpmTaskNotifyService bpmTaskNotifyService;

    @Autowired
    BpmDynamicAssignMapper bpmDynamicAssignMapper;

    @Autowired
    TaskDeadTimeProcessor taskDeadTimeProcessor;

    public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
            .add(FlowableEngineEventType.TASK_CREATED)
            .add(FlowableEngineEventType.TASK_ASSIGNED)
            .add(FlowableEngineEventType.TASK_COMPLETED)
            .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
            .build();

    public BpmTaskEventListener(){
        super(TASK_EVENTS);
    }

    @Override
    protected void taskCreated(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();
        this.bpmTaskNotifyService.notify(task,FlowableEngineEventType.TASK_CREATED);
        this.taskDeadTimeProcessor.doDeadTime(task,FlowableEngineEventType.TASK_CREATED);

        this.taskService.createTaskExt(task);
    }

    @Override
    protected void taskCompleted(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();
        this.bpmTaskNotifyService.notify(task,FlowableEngineEventType.ACTIVITY_CANCELLED);
        this.taskDeadTimeProcessor.doDeadTime(task,FlowableEngineEventType.ACTIVITY_CANCELLED);

        this.taskService.updateTaskExtComplete((task));
    }

    @Override
    protected void taskAssigned(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();
        String  actId      =    task.getTaskDefinitionKey();
        String  assignee   =    task.getAssignee();
        String  actName    =    task.getName();
        String  processInstanceId = task.getProcessInstanceId();
        log.info("taskAssigned: actId:{} actName:{} assignee:{}",actId,actName,assignee);

        BpmDynamicAssignDo bpmDynamicAssignDo = this.bpmDynamicAssignMapper.getByProcessInstanceIdAndActId(processInstanceId,actId);
        /**
         * 检查是否有动态 设置审批人
         */
        if(Objects.nonNull(bpmDynamicAssignDo) ){
            String replace_assign =   bpmDynamicAssignDo.getAssignee();
            assignee = replace_assign;
            task.setAssignee(assignee);
            log.info("存在动态指定审核人:{}",replace_assign);
            /**
             * 修改指定审核人
             */
            bpmDynamicAssignDo.setStatus(1);
            this.bpmDynamicAssignMapper.updateById(bpmDynamicAssignDo);
            this.taskService.claim(task.getId(),replace_assign);
        }
        this.taskDeadTimeProcessor.doDeadTime(task,FlowableEngineEventType.TASK_ASSIGNED);
        this.taskService.updateTaskExtAssign(task);
    }

    @Override
    protected void activityCancelled(FlowableActivityCancelledEvent event) {

        List<HistoricActivityInstance> activityList = activityService.getHistoricActivityListByExecutionId(event.getExecutionId());
        if (CollUtil.isEmpty(activityList)) {
            log.error("[activityCancelled][使用 executionId({}) 查找不到对应的活动实例]", event.getExecutionId());
            return;
        }
        // 遍历处理
        activityList.forEach(activity -> {
            if (StrUtil.isEmpty(activity.getTaskId())) {
                return;
            }
            TaskEntityImpl task =new TaskEntityImpl();
            task.setId(activity.getTaskId());
            task.setAssignee(activity.getAssignee());
            task.setProcessDefinitionId(activity.getProcessDefinitionId());

            this.bpmTaskNotifyService.notify(task,FlowableEngineEventType.ACTIVITY_CANCELLED);
            this.taskDeadTimeProcessor.doDeadTime(task,FlowableEngineEventType.ACTIVITY_CANCELLED);

            taskService.updateTaskExtCancel(activity.getTaskId());
        });
    }

}
